package com.jxm.validation;

import com.jxm.annotation.CheckValue;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

import java.lang.reflect.Method;
import java.math.BigDecimal;

/**
 * 枚举校验注解处理类
 */
public class CheckValueValidator implements ConstraintValidator<CheckValue, Object> {
    private String[] strValues;
    private Class<? extends Enum> enumClass;
    private String verifyValue;

    @Override
    public void initialize(CheckValue constraintAnnotation) {
        strValues = constraintAnnotation.strValues();
        enumClass = constraintAnnotation.enumValue().enumValue();
        verifyValue = constraintAnnotation.enumValue().key();
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        Method getName = null;
        if (!enumClass.equals(Enum.class)) {
            try {
                getName = enumClass.getMethod(verifyValue);
            } catch (NoSuchMethodException e) {
                // verifyValue 需要和枚举中的getXxx方法名一致
                throw new RuntimeException("传入的key需要和方法名一致");
            }

            Enum[] enumConstants = enumClass.getEnumConstants();
            for (Enum enumConstant : enumConstants) {
                try {
                    Object invoke = getName.invoke(enumConstant);
                    if (verify(value, invoke)) {
                        return true;
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e.getMessage());
                }
            }
        } else if (strValues.length > 0) {
            for (String s : strValues) {
                if (verify(value, s)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 校验
     *
     * @param value 用户传的参数
     * @param param 需要校验的参数
     * @return
     */
    private boolean verify(Object value, Object param) {
        if (value instanceof String) {
            return value.equals(String.valueOf(param));
        } else if (value instanceof Integer) {
            return value.equals(Integer.valueOf(String.valueOf(param)));
        } else if (value instanceof BigDecimal) {
            return value.equals(new BigDecimal(String.valueOf(param)));
        } else if (value instanceof Double) {
            return value.equals(Double.valueOf(String.valueOf(param)));
        }
        return false;
    }
}